import NDB from "./NDBTS";
import { AppName, GameConfig } from "../GameConfig";
import { eventManager } from "./eventManager";
import NetworkMessage from "./NetworkMessage";
import MessageData, { GameType } from "./MessageData";
import { isProd } from "./util";
import { Node } from "cc";

export interface UserInfo {
    accountType: string;
    avatar: string;
    lang: string;
    userId: string;
    userName: string;
}

export interface RoomInfo {
    display_id: string;
    level: number;
    owner_avatar: string;
    owner_id: string;
    owner_name: string;
    room_id: string;
    share_url: string;
}

export interface RankItemData {
    "id": string,
    "icon": string,
    "name": string,
    "ranking": number,
    "coin": number,
    "noble": string,
    "noble_badge": string,
    "noble_level": string,
    "noble_text_color": string,
}

export enum EAllGameRankType {
    WEEK = "week",
    DAY = "day",
}

export interface RankNewData {
    leaderboard: RankItemData[];
    last_week_top_rank?: RankItemData;
    /** 周榜奖励 日榜没有 */
    reward?: number[];
}

export interface AssetsData {
    chips: number;
    coin: number;
    crystal: number;
    diamond: number;
}

export const ERROR_NO_ENOUGH_COIN = 81008;
export const ERROR_PARAM_INVALID = 81001;
export const ERROR_NO_COIN = 89001;
export const ERROR_NOT_CURRENT_GAME = 92015;

/** 挑战超时 */
export const CHALLENGE_TIME_OUT = 50019;

/** 加注超限制 */
export const ERROR_RAISE_MORE_THAN_MAX = 50019;

/** 账户冻结 */
export const FROZEN = 30004;
/** 筹码冻结 */
export const CHIPFROZEN = 30007;
/** 被禁用 */
export const FORBIDDEN = 50001;
/** 系统正在维护中 */
export const SYSTEMFIX = 50002;
/** 降级 */
export const DOWNGRADE = 50003;

export const AppDeepLinkMap = {
    [AppName.YOYO]: "yoyo",
    [AppName.U2]: "u2",
}

export default class NetworkManager {
    public static NET_USER_CONST_PATH = 'https://user.funshareapp.com/';                   //个人信息请求；
    public static NET_API_CONST_PATH = 'https://api.funshareapp.com/';                     //截图等功能请求；
    public static NET_IAP_CONST_PATH = 'http://iap.funshareapp.com/';                     //金币相关接口；
    public static NET_CONST_PATH = 'https://game.funshareapp.com/';                        //正式环境http地址；
    public static CHAT_API_CONST_PATH = 'https://chatroom.funshareapp.com/';               //聊天室的请求；
    public static TRACE_BUG_PATH = 'https://game.funshareapp.com/'

    public static ACTIVITY_CONST_PATH = 'https://activity.funshareapp.com/';

    public static ZCLUB_PATH = 'http://dev.zclub.chainxy.co/'

    public static socketDatas: Array<any> = new Array<any>();
    public static isPushmessage = false;

    public static gameSource: string = "";

    static Init() {
        NetworkManager.setNetworkConfiguration();
        NetworkManager.gameSource = NetworkManager.getUrlParameterValue('source');

        NetworkMessage.GETUSERINFO = `v1/${GameConfig.gameName}/user/mine/`;    //获取个人信息;
        NetworkMessage.PLAYPOCKER = `v1/${GameConfig.gameName}/play_poker/`;     //出牌;
        NetworkMessage.SINGLE_JOIN_GAME = `v1/${GameConfig.gameName}/single/join`;
    }

    /**测试和正式环境自动区分;*/
    public static setNetworkConfiguration() {
        let source = window.location.href;
        if (source.match('prod')) {
            console.log("正式环境");
            let domine = 'funshareapp';
            if (GameConfig.appName == AppName.U2) {
                domine = 'amurmur';
                this.NET_CONST_PATH = `https://game.${domine}.app/`;                    //正式环境http地址；
                this.NET_USER_CONST_PATH = `https://user.${domine}.app/`;               //个人信息请求；
                this.NET_API_CONST_PATH = `https://api.${domine}.app/`;                 //截图等功能请求；
                this.NET_IAP_CONST_PATH = `https://iap.${domine}.app/`;                 //金币相关接口；
                this.CHAT_API_CONST_PATH = `https://chatroom.${domine}.app/`;           //聊天室的请求；
                this.TRACE_BUG_PATH = `https://game.${domine}.app/`;
                this.ACTIVITY_CONST_PATH = `https://activity.${domine}.app/`;
            } else if (GameConfig.appName == AppName.YOYO) {
                this.NET_CONST_PATH = `https://game.funshareapp.com/`;                    //正式环境http地址；
                this.NET_USER_CONST_PATH = `https://user.funshareapp.com/`;               //个人信息请求；
                this.NET_API_CONST_PATH = `https://api.funshareapp.com/`;                 //截图等功能请求；
                this.NET_IAP_CONST_PATH = `https://iap.funshareapp.com/`;                 //金币相关接口；
                this.CHAT_API_CONST_PATH = `https://chatroom.funshareapp.com/`;           //聊天室的请求；
                this.TRACE_BUG_PATH = `https://game.funshareapp.com/`;
                this.ACTIVITY_CONST_PATH = `https://activity.funshareapp.com/`;
                this.ZCLUB_PATH = "https://api.zclub.app/";
            }

        } else {
            console.log("测试环境");
            this.NET_CONST_PATH = 'http://game.funshareapp.com/';                //测试环境http地址;
            this.NET_USER_CONST_PATH = 'http://user.funshareapp.com/';               //个人信息请求；
            this.NET_API_CONST_PATH = 'https://api.funshareapp.com/';                 //截图等功能请求；
            this.NET_IAP_CONST_PATH = 'http://test_iap-http.gateway.funshareapp.com/';                 //金币相关接口；
            this.CHAT_API_CONST_PATH = 'http://chatroom.funshareapp.com/';           //聊天室的请求；
            this.TRACE_BUG_PATH = 'http://ldy_game-http.gateway.funshareapp.com/';
            this.ACTIVITY_CONST_PATH = 'http://denglinfeng_activity-http.gateway.funshareapp.com/';
            this.ZCLUB_PATH = "http://dev.zclub.chainxy.co/";

        }
        // this.NET_CONST_PATH = 'http://test_game-http-server.gateway.funshareapp.com/';                //测试环境http地址;
        // this.NET_USER_CONST_PATH = 'http://user.funshareapp.com/';               //个人信息请求；
        // this.NET_API_CONST_PATH = 'https://api.funshareapp.com/';                 //截图等功能请求；
        // this.NET_IAP_CONST_PATH = 'http://test_iap-http.gateway.funshareapp.com/';                 //金币相关接口；
        // this.CHAT_API_CONST_PATH = 'http://chatroom.funshareapp.com/';   

    }

    /**获取页面参数值;*/
    public static getUrlParameterValue(name) {
        let href = window.location.href;
        var query = href.substring(1);
        var vars = query.split("?");
        if (!vars[1]) {
            return '';
        }
        var argment = vars[1].split("&");
        for (var i = 0; i < argment.length; i++) {
            var pair = argment[i].split("=");
            if (pair[0] == name) { return pair[1]; }
        }
        return '';
    }
    /*
          通过http获取数据；
          * @method {String} get,post,put,del
          * @url {String} 请求url
          * @params {sendData} 发送参数
      */
    public static async httpResult(method, url, sendData = {}, callback, number = 2) {
        let sendUrl = `${this.NET_CONST_PATH}${url}`;
        console.log('sendUrl:' + sendUrl);
        let result = null;

        result = await NDB.request(method, sendUrl, sendData);
        console.log("result is ", result);
        if (JSON.stringify(result) == "{}") {
            // ios超时返回一个空对象，android超时返回 {err_code: -1,err_msg: "time out"}
            callback && callback({ err_code: -1, err_msg: "time out" });
            return;
        }
        if (result.err_code && Number(result.err_code) == 500 && number > 0) {
            //返回500，再次请求;
            //console.log('返回500，再次请求');
            number = number - 1;
            this.httpResult(method, url, sendData, callback, number);
            return;
        }
        callback && callback(result);
    }

    /**
     * 偶现问题打点定位
     * @param  {string} method 'post' || 'get'
     * @param  {string} url 请求url
     * @param  {Object} sendData={}
     * @param  {Function} callback
     * @param  {number} number=2
     */
    public static async httpResultByHost(method, url, sendData = {}, callback, number = 2) {
        let sendUrl = `${this.TRACE_BUG_PATH}${url}`;
        console.log('偶现问题sendUrl:' + sendUrl);
        let result = await NDB.request(method, sendUrl, sendData);
        if (result.err_code && Number(result.err_code) == 500 && number > 0) {
            //返回500，再次请求;
            //console.log('返回500，再次请求');
            number = number - 1;
            this.httpResult(method, url, sendData, callback, number);
            return;
        }
        callback && callback(result);
    }

    /**
     * 发送bug定位信息
     * @param  {string} gameName 游戏名称
     * @param  {string} error 错误码
     * @param  {string} error_msg 定位信息
     */
    public static async sendBugTraceByMessage(gameName: string, error: string, error_msg: string) {
        console.log('发送消息');
        await this.httpResultByHost('post', 'v1/base/bug/trace', {
            game: gameName,
            error,
            error_msg,
        }, () => { });
    }
    /**获取资产的接口 */
    public static async httpIAPResult(method, url, sendData = {}, callback): Promise<any> {
        const urls = ['v1/leaderboard', 'v2/leaderboard', 'v1/activity'];
        let sendUrl = `${this.NET_IAP_CONST_PATH}${url}`;
        if (urls.some(item => url.indexOf(item) >= 0)) {
            sendUrl = `${this.ACTIVITY_CONST_PATH}${url}`;
        }

        let result = await NDB.request(method, sendUrl, sendData);
        console.log('result is ', result);
        callback && callback(result);
        return result;
    }

    /**发送socket数据
    @param messageType 消息号
    @param sendData 需要发送数据
    */
    public static socketSend(messageType, sendData = {}) {
        NDB.run('onSocketSend', { method: messageType, data: sendData });
    }

    /**派发收到的socket消息;*/
    public static emitSocketMessage(message) {
        // console.log('message is ', message);
        const method: string = message.method;
        eventManager.emit("emit_message", message);

        if (method == "switch_room") {
            eventManager.emit(NetworkMessage.MESSAGE_SWITCH_ROOM, { data: message });
        }
        if (method == "updateVolumeIndication") {
            eventManager.emit(NetworkMessage.MESSAGE_UPDATA_VOLUME_INDICATION, { data: message });
        }
        if (method == "emoji_on_mic") {
            eventManager.emit(NetworkMessage.MESSAGE_EMOJI_ON_MIC, { data: message });
        }
        if (method === 'response_ws_status') {
            console.log('message is ', message);
            eventManager.emit(NetworkMessage.MESSAGE_REQUEST_WS_STATUS, { data: message });
        }
        if (method === 'task_complete') {
            eventManager.emit(NetworkMessage.MESSAGE_TASK_COMPLETE, { data: message });

        }
        if (MessageData.switch_room_id) {
            if (MessageData.gameType == GameType.single
                && message
                && message.channel
                && message.channel.type == MessageData.gameName
                && message.data
                && message.data.source_id
                && MessageData.switch_room_id != message.data.source_id) {
                console.log("===================>不是本局消息<===================");
                return;
            }
        }
        eventManager.emit(NetworkMessage.MESSAGE_MAIN_SOCKET, { data: message });
        if (this.isPushmessage) {
            let method = message.method;
            if (method && method == MessageData.gameName + '_playing' || method == MessageData.gameName + '_completed') {
                if (MessageData.gameName == 'ludo') {
                    this.socketDatas.push(message.data);
                } else {
                    this.socketDatas.push(message);
                }
            }
        }

        if (method == `${MessageData.gameName}_matching`) {
            eventManager.emit(NetworkMessage.MESSAGE_MATCHING, { data: message });
        }
        if (method == `${MessageData.gameName}_playing`) {
            eventManager.emit(NetworkMessage.MESSAGE_PLAYER, { data: message });
        }
        if (method == `${MessageData.gameName}_completed`) {
            eventManager.emit(NetworkMessage.MESSAGE_COMPLETED, { data: message });
        }
        if (MessageData.gameName === 'uno') {
            console.log('Uno 游戏 method is ', method);
        }
        if (method == `uno_match`) {
            eventManager.emit(NetworkMessage.MESSAGE_MATCHING, { data: message });
        }
        if (method == `uno_play`) {
            console.log('socket uno_play');
            eventManager.emit(NetworkMessage.MESSAGE_PLAYER, { data: message });
        }
        if (method == `uno_completed`) {
            eventManager.emit(NetworkMessage.MESSAGE_COMPLETED, { data: message });
        }

        if (method == "host_info") {
            eventManager.emit("host_info", { data: message });
        }

        if (method == `group_info`) {
            console.log('group_info');
            eventManager.emit(NetworkMessage.GROUP_INFO, { data: message });
        }

        if (method === 'mic_users') {
            eventManager.emit(NetworkMessage.MESSAGE_MIC_USERS, { data: message });
        }
        eventManager.emit("socket_message", message);

    }
    /** 获取首条socket消息*/
    public static getFirstSocket() {
        if (this.socketDatas.length > 0)
            return this.socketDatas[0];
        else
            return null;
    }
    /** 删除首条socket消息*/
    public static deleteFirstSocket() {
        if (this.socketDatas[0]) {
            this.socketDatas.splice(0, 1);
        }

    }
    /** 清除收到的socket消息*/
    public static clearSocketDatas() {
        this.socketDatas = new Array<any>();
        this.socketDatas.length = 0;
    }
    //获取最后的消息;
    public static getLastMessage() {
        // console.log("最后的消息",this.socketDatas);
        let len = this.socketDatas.length;
        return this.socketDatas[len - 1];
    }

    public static async httpUserResult(method, url, sendData = {}, callback) {
        let sendUrl = `${this.NET_USER_CONST_PATH}${url}`;
        let result = await NDB.request(method, sendUrl, sendData);
        callback && callback(result);
    }

    /**
     * @param  {string} method 网络请求的方法
     * @param  {string} url 网络请求的路径
     * @param  {any}   sendData={} body参数
     * @param  {Function} callback 网络请求正常响应回调
     * @param  {Number} number=2 重试次数
     */
    public static async httpAHTResult<T>(method: string, url: string, sendData = {}, callback: Function, number = 2) {
        let sendUrl = `${this.ZCLUB_PATH}${url}`;
        console.log('sendUrl is ', sendUrl);
        let result = await NDB.request(method, sendUrl, sendData);
        if (result.err_code && Number(result.err_code) == 500 && number > 0) {
            number = number - 1;
            this.httpAHTResult(method, url, sendData, callback, number);
            return;
        }
        console.log("request result is ", result);
        callback && callback(result);
        return result as T;
    }

    public static async httpTestUserResult(method, url, sendData = {}, callback) {
        let sendUrl = url;
        let result = await NDB.request(method, sendUrl, sendData);
        console.log('result is ', result);
        callback && callback(result);
    }

    public static async httpAPIResult(method, url, sendData = {}, callback) {
        let sendUrl = `${this.NET_API_CONST_PATH}${url}`;
        let result = await NDB.request(method, sendUrl, sendData);
        // return result;
        callback && callback(result);
    }

    //通知APP显示用户头像；
    public static showPlayerInfo(uid) {
        NDB.showPlayerInfo(uid);
    }

    //获取排行榜数据;
    public static getRankData(callback) {
        let url = 'v1/leaderboard/game/ranks/?type=game_dmn_day';
        NetworkManager.httpIAPResult('get', url, {}, (data) => {
            callback(data);
        });
    }

    public static goH5Recharge() {
        let url = "zclub://openapp?page=web_view&data=" + encodeURIComponent("http://t.fslk.co/staging/p/zclub_chip_exchange/index.html");
        if (isProd()) {
            url = "zclub://openapp?page=web_view&data=" + encodeURIComponent("https://talk.zclub.app/p/zclub_chip_exchange/index.html");
        }

        NDB.openDeepLink(url);
    }

    /**强制更新游戏;*/
    public static updateGame() {
        // NDB.openDeepLink('yoyo://start_activity/play_store');  //market://details?id=com.fun.share
        window.location.href = 'market://details?id=com.fun.share';
    }

    /**跳转道具商城;*/
    public static goStore() {
        let url = "http://liulong_game-http.gateway.funshareapp.com/v1/base/bug/trace";
        if (isProd()) {
            url = "https://game.funshareapp.com/v1/base/bug/trace";
        }
        let obj = {
            eventName: "click_store",
            name: `${GameConfig.gameName}`,
        }
        NDB.sendAutoJoinEvent(obj);

        let obj2 = {
            game: `${GameConfig.gameName}`,
            error: "store_click",
            error_msg: "store_click"
        }
        NDB.request('post', url, obj2).then((res) => {
            console.warn("res is ", res);
        })
        let deepLink = `${this.assembleDeepLinkProtocal()}://start_activity/store?title_tab=game_tools&tab=game_ludo`;
        // @ts-ignore
        if (GameConfig.gameName == 'dominoe') {

            deepLink = `${this.assembleDeepLinkProtocal()}://start_activity/store?title_tab=game_tools&tab=game_frame`;
        }
        NDB.openDeepLink(deepLink);
    }

    public static assembleDeepLinkProtocal() {
        let protocal = AppDeepLinkMap[GameConfig.appName];
        return protocal;
    }

    /**显示toast;*/
    public static showToast(showStr: string) {
        NDB.toast({ msg: showStr, long: true });
    }
    //购买游戏币;
    public static buyGameCion() {
        let protocal = AppDeepLinkMap[GameConfig.appName];
        NDB.openDeepLink(`${protocal}://start_activity/recharge?tab=game_coin&from=ludo`);
    }

    public static goZclubRecharge() {
        NDB.openDeepLink('zclub://openapp?page=wallet_spending');
    }


    //退出游戏;
    public static exitGame() {
        NDB.closeWebView();
    }

    /**
     * 根据app类型适配跳转充值连接
     */
    public static bugCoin() {
        if (GameConfig.appName === AppName.YOYO) {
            NDB.openDeepLink('yoyo://start_activity/recharge');
        } else if (GameConfig.appName == AppName.U2) {
            NDB.openDeepLink('amurmur://start_activity/recharge');
        }
    }

    public static async shareGameOrImage(shareText, imgUrl, callback) {
        let result = await NDB.shareGameOrImage(shareText, imgUrl);
        callback && callback(result);
    }

    public static async renderTextureShare(callback) {
        let result = await NDB.renderTextureShare();
        callback && callback(result);
        let newData = result['result']['filePath'];
        let shareText: string = 'Come to join this chatroom and play incredible game!  ' + MessageData.shareUrl;
        let resultShare = await NDB.shareGameOrImage(shareText, newData);
    }

    public static subNickName(nameStr: string, subCount: number = 8) {
        if (nameStr.length > subCount) {
            nameStr = nameStr.substring(0, subCount) + '...';
        }
        return nameStr;
    }

    //设置切换纹理的动作;
    public static setChangeSpriteFrameAction(node1: Node, node2: Node) {

        // let scaleF0 = cc.scaleTo(0.3, 0.9);
        // let scaleF1 = cc.scaleTo(0.4, 1.1);
        // let scaleF2 = cc.scaleTo(0.2, 0.9);
        // let scaleF3 = cc.scaleTo(0.2, 1);
        // let callfunc = cc.callFunc(() => {
        //     let ro = cc.rotateBy(0.6, 180);
        //     let deTime = cc.delayTime(0.4);
        //     let hi = cc.fadeOut(0.2);
        //     let call = cc.callFunc(() => {
        //         node2.active = false;
        //     });
        //     node2.active = true;
        //     node2.runAction(cc.sequence(cc.spawn(ro, cc.sequence(deTime, hi)), call));
        // });
        // node1.runAction(cc.sequence(scaleF0, callfunc, scaleF1, scaleF2, scaleF3));
    }

    /**
     * 获得榜单 分为周榜和日榜
     * @param  {'day' | week} type  day week
     */
    public static async getDayOrWeekRank(type: 'day' | 'week', areaType: boolean = false, callback?: Function): Promise<RankNewData> {
        return new Promise((resolve, reject) => {
            let gameName = GameConfig.gameName;
            // @ts-ignore
            if (GameConfig.gameName == 'catslots') {
                gameName = 'slot';
            }
            this.httpIAPResult('get', `${NetworkMessage.ALLGAMERANK}game_${gameName}_${type}&is_region=${areaType}`, {}, (data: RankNewData) => {
                callback && callback(data);
                resolve(data);
            }).catch(e => {
                reject(e);
            })
        })
    }

    static async getDayOrWeekRankZclub(timeType: string, callback?: Function): Promise<any> {
        let url = `v1/games/master/leaderboard/${timeType}/${GameConfig.gameName}/`;
        let res = await this.httpAHTResult('get', url, {}, () => { });
        console.log("res is ", res);
        callback && callback(res);
        return res;
    }

    public static rankHttpIsOK(response: any) {
        if (!response) return false;
        return response['leaderboard'] ? true : false;
    }


    /**
     * 打开某个人的语音输入功能
     * @param  {number|string} userId
     */
    public static openUserVoice(userId: number | string) {
        NDB.run('gameRoom', { func: 'voice', extra: { is_open: true, user_id: userId } });
    }

    /**
     * 关闭某个人的语音输入功能
     * @param  {number|string} userId
     */
    public static closeUserVoice(userId: number | string) {
        NDB.run('gameRoom', { func: 'voice', extra: { is_open: false, user_id: userId } });
    }

    public static getAssets(callback?: Function) {
        return new Promise((resolve, reject) => {
            this.httpIAPResult('get', NetworkMessage.ASSETS, {}, null).then((data: AssetsData) => {
                console.log("data is ", data);
                if (data['err_code']) {
                    reject(data);
                    return;
                }
                resolve(data);
                callback && callback(data);
            });
        });
    }

    public static async getUserInfo(): Promise<{ avatar: string, username: string, userId: string }> {
        let userInfo = await NDB.getUserInfo() as { "result": UserInfo };

        const avatar = userInfo.result.avatar;
        const userName = userInfo.result.userName;
        const userId = userInfo.result.userId;

        return { avatar, username: userName, userId };
    }

    /**
     * 是否显示语音按钮
     * @param  {boolean} flag true: 显示 false: 隐藏
     */
    public static isShowVoiceBtn(flag: boolean) {
        console.warn(`${flag == true ? '显示' : '隐藏'}语音按钮`);
        let status = 'match';
        if (!flag) {
            status = 'start';
        }
        NDB.run('gameRoom', {
            func: 'game_status',
            game: 'detective_vs_lurker',
            extra: { status }
        });
    }

}